package com.xg.sys.controller;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xg.frame.log.annotation.LogAnnotation;
import com.xg.sys.entity.SysUser;
import com.xg.sys.entity.SysUserOrgEntity;
import com.xg.sys.entity.SysUserRole;
import com.xg.sys.service.SysOrganizationService;
import com.xg.sys.service.SysUserOrgService;
import com.xg.sys.service.SysUserRoleService;
import com.xg.sys.service.SysUserService;
import com.xg.sys.vo.PageVO;
import com.xg.sys.vo.SysUserVO;
import com.xg.sys.vo.TreeVO;
import com.xg.utils.DDDUtils;
import com.xg.frame.constant.SysConstant;
import com.xg.frame.constant.UrlConstant;
import com.xg.frame.entity.R;
import com.xg.frame.utils.MD5Utils;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.validation.constraints.NotBlank;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author tzt
 * @date Created in 2021/8/9 16:55
 * @description：用户处理器
 * @modified By：
 */
@Controller
@RequestMapping(UrlConstant.WEB_ADMIN_URL + "/user")
public class UserController {
    @Resource
    private SysUserService sysUserService;
    @Resource
    private SysUserRoleService sysUserRoleService;
    @Resource
    private SysOrganizationService sysOrganizationService;
    @Resource
    private SysUserOrgService sysUserOrgService;

    /**
     * 获取用户展示页面
     *
     * @param model
     * @return
     * @throws Exception
     */
    @GetMapping
    public String index(Model model) throws Exception {
        return "/sys/user/list";
    }

    @GetMapping(value = "/query")
    @ResponseBody
    public PageVO<SysUserVO> query(String username, String surname, String status, Page<SysUser> page) throws Exception {
        page = sysUserService.page(
                page,
                new LambdaQueryWrapper<SysUser>()
                        .like(StringUtils.isNotEmpty(username), SysUser::getUsername, username)
                        .like(StringUtils.isNotEmpty(surname), SysUser::getSurname, surname)
                        .eq(StringUtils.isNotEmpty(status), SysUser::getStatus, status)
                        .orderByDesc(SysUser::getCreateTime)
        );
        return new PageVO<SysUserVO>()
                .setTotal(page.getTotal())
                .setRows(DDDUtils.collection(page.getRecords(), SysUserVO.class));
    }

    @GetMapping(value = "/edit")
    public String edit(Model model, Long id) {
        SysUserVO user = new SysUserVO();
        if (Objects.isNull(id)) {
            user.setStatus(SysConstant.STATUS_Y);
            model.addAttribute("title", SysConstant.ADD);
        } else {
            SysUser byId = sysUserService.getById(id);
            BeanUtils.copyProperties(byId, user);
            model.addAttribute("title", SysConstant.EDIT);
        }
        model.addAttribute("user", user);
        return "/sys/user/edit";
    }

    @LogAnnotation(module = UrlConstant.sysCenter, describe = "用户新增修改")
    @RequiresPermissions("user:save")
    @PostMapping("/save")
    @ResponseBody
    public R save(SysUserVO userVO, Model model) {
        if (Objects.isNull(userVO.getId())) {
            List<SysUser> userList = sysUserService.getByUserName(userVO.getUsername());
            if (userList.isEmpty()) {
                SysUser sysUser = new SysUser();
                BeanUtils.copyProperties(userVO, sysUser);
                sysUser.setPassword(MD5Utils.stringToMD5(SysConstant.PASSWORD));
                sysUserService.save(sysUser);
                return R.ok().message("保存成功！");
            } else {
                return R.error().message("已存在相同账号！");
            }
        } else {
            sysUserService.update(
                    new LambdaUpdateWrapper<SysUser>()
                            .eq(SysUser::getId, userVO.getId())
                            .set(SysUser::getSurname, userVO.getSurname())
                            .set(SysUser::getStatus, userVO.getStatus())
            );
            return R.ok().message("修改成功！");
        }
    }

    @GetMapping("/validDel")
    @ResponseBody
    public R validDel(@NotBlank String id) {
        String[] ids = id.split(",");
        List<Long> idList = Arrays.stream(ids).map(item -> Long.parseLong(item)).collect(Collectors.toList());
        List<SysUserOrgEntity> oidList = sysUserOrgService.getOidListByUidList(idList);
        List<SysUserRole> ridList = sysUserRoleService.getRidListByUidList(idList);
        if (CollectionUtils.isNotEmpty(oidList) || CollectionUtils.isNotEmpty(ridList)) {
            return R.error().message("该用户已经分配角色/机构，是否确认删除该用户?");
        } else {
            return R.ok();
        }

    }

    @LogAnnotation(module = UrlConstant.sysCenter, describe = "用户删除")
    @RequiresPermissions("user:del")
    @GetMapping("/del")
    @ResponseBody
    public R del(@NotBlank String id) {
        String[] ids = id.split(",");
        List<Long> idList = Arrays.stream(ids).map(item -> Long.parseLong(item)).collect(Collectors.toList());
        boolean b = sysUserService.removeUser(idList);
        return b ? R.ok() : R.error();
    }

    @LogAnnotation(module = UrlConstant.sysCenter, describe = "用户关联角色")
    @RequiresPermissions("user:role")
    @PostMapping("/relateRole")
    @ResponseBody
    public R relateRole(@RequestParam List<Long> roleIds, @RequestParam Long userId) {
        sysUserRoleService.relateRole(roleIds, userId);
        return R.ok();
    }

    @PostMapping("/relateOrgIndex")
    @ResponseBody
    public List<TreeVO> relateOrgIndex(Long userId) throws NoSuchMethodException {
        List<TreeVO> treeVOList = sysOrganizationService.treeForYkk(userId);
        return treeVOList;
    }

    @LogAnnotation(module = UrlConstant.sysCenter, describe = "用户重置密码")
    @RequiresPermissions("user:rest")
    @RequestMapping(value = "editPassword")
    @ResponseBody
    public R editPassword(String id, String oldPwd, String newPwd, HttpServletRequest request) throws Exception {
        JSONObject returnObj = new JSONObject();
        SysUser user = sysUserService.getById(Long.valueOf(id));
        if (user != null) {
            if (user.getPassword().equals(MD5Utils.stringToMD5(oldPwd))) {
                user.setPassword(MD5Utils.stringToMD5(newPwd));
                if (user.getLoginTime() == null) {
                    user.setLoginTime(new Date()).setLoginIp(request.getRemoteAddr());
                }
                sysUserService.updateById(user);
                return R.ok();
            } else {
                return R.error().message("原密码错误");
            }
        } else {
            return R.error().message("用户不存在");
        }
    }

    @LogAnnotation(module = UrlConstant.sysCenter, describe = "用户关联组织")
    @RequiresPermissions("user:org")
    @PostMapping("/relateOrg")
    @ResponseBody
    public R relateOrg(Long orgId, Long userId) {
        SysUserOrgEntity userOrgEntity = new SysUserOrgEntity();
        userOrgEntity.setOid(orgId);
        userOrgEntity.setUserId(userId);
        sysUserOrgService.relateUser(userOrgEntity);
        return R.ok();
    }

    @GetMapping("/view")
    public String view(Model model) throws Exception {
        SysUser sysUser = (SysUser) SecurityUtils.getSubject().getPrincipal();
        model.addAttribute("user", sysUser);
        return "/sys/user/view";
    }

    @LogAnnotation(module = UrlConstant.sysCenter, describe = "用户解锁")
    @GetMapping("/unlock")
    @ResponseBody
    public R unlock(@NotBlank Long id) {
        boolean b = sysUserService.update(
                new LambdaUpdateWrapper<SysUser>()
                        .eq(SysUser::getId, id)
                        .set(SysUser::getErrNum, 0)
                        .set(SysUser::getLockTime, null)
        );

        return b ? R.ok() : R.error();
    }
}
